package com.yswy.app.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yswy.app.service.WxOpenLinkService;
import com.yswy.app.service.WxProgramConfigService;
import com.yswy.common.exception.WxLoginException;
import com.yswy.common.utils.HttpUtil;
import com.yswy.common.utils.redis.RedisConstants;
import com.yswy.common.utils.redis.RedisUtil;
import com.yswy.domain.entity.WxOpenLink;
import com.yswy.domain.entity.WxProgramConfig;
import com.yswy.domain.mapper.WxOpenLinkMapper;
import com.yswy.domain.mapper.WxProgramConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: WxPayServiceImpl
 * @Description: 微信支付接口
 * @Author: Matt
 * @Date: 2020/11/11 10:46
 **/
@Service
@Slf4j
public class WxProgramConfigServiceImpl extends ServiceImpl<WxProgramConfigMapper, WxProgramConfig>
        implements WxProgramConfigService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WxOpenLinkService wxOpenLinkService;

    @Override
    public WxProgramConfig getWxProgramConfig() {
        WxProgramConfig wxProgramConfig = null ;
        String key = RedisConstants.WxProgramConfig_CASH ;
        if (redisUtil.hasKey(key)){
            wxProgramConfig = (WxProgramConfig)redisUtil.getObejct(key);
        }else {
            wxProgramConfig = getOne(new LambdaQueryWrapper<WxProgramConfig>()
                    .eq(WxProgramConfig::getKeyStatus , 0)
                    .last("limit  1"));
            if (wxProgramConfig!= null){
                String AccessToken  = sendAccessToken(wxProgramConfig);
                wxProgramConfig.setAccessToken(AccessToken);
                updateById(wxProgramConfig);
                redisUtil.setForObjectTimeCustom(key, wxProgramConfig, 1, TimeUnit.HOURS);
            }else {
                return null ;
            }
        }
        return wxProgramConfig ;
    }

    @Override
    public String sendAccessToken( WxProgramConfig wxProgramConfig) {

        String access_token = HttpUtil.doGet("https://api.weixin.qq.com/cgi-bin/token?" +
                "grant_type=client_credential"
                + "&appid="+wxProgramConfig.getAppId()
                + "&secret=" + wxProgramConfig.getAppSecret());

        log.info("获取 access_token " + access_token);
        if (access_token.contains("errcode")){
            throw new WxLoginException("获取Access Token失败");
        }
        JSONObject access_tokenJson = JSONObject.parseObject(access_token);
        String sessionKey = access_tokenJson.getString("access_token");
        return sessionKey ;
    }

    @Override
    public String sendOpenlink(WxProgramConfig wxProgramConfig , Map<String, String> queryMap) {
        String url = "https://api.weixin.qq.com/wxa/generatescheme?access_token=" +wxProgramConfig.getAccessToken() ;
        Map<String , Object> map = new HashMap<>() ;
        map.put("is_expire" , true);
        map.put("expire_type" , 1);
        map.put("expire_interval" , 10);
        Map<String , String> jump_wxa = new HashMap<>() ;

        if (queryMap != null){
            jump_wxa.put("path" , "pages/splash/splash");
            String query = "goodsId="+queryMap.get("goodsId");
//            for (String key : queryMap.keySet()) {
//                query +=  key+"="+queryMap.get(key)+"&";
//            }
            log.info("query    :  "+query);
            jump_wxa.put("query" , query);
        }else {
            jump_wxa.put("path" , "pages/splash/splash");
            jump_wxa.put("query" , "type3=1&type4=2");
        }
//        正式版为"release"，体验版为"trial"，开发版为"develop"
        jump_wxa.put("env_version" , "release");
        map.put("jump_wxa" , jump_wxa);
        String open_link = HttpUtil.doPost(url , JSONObject.parseObject(JSONObject.toJSONString(map)));

        log.info("获取 open_link " + open_link);
        JSONObject open_linkJson = JSONObject.parseObject(open_link);
        if (!open_linkJson.getString("errcode").equals("0")){
            throw new WxLoginException("获取open_link失败");
        }

        String openlink = open_linkJson.getString("openlink");
        return openlink ;
    }

    @Override
    public String getOpenlink(String ip) {
        log.info(ip);
        String key = RedisConstants.WxProgram_OpenLink+ip ;
        String Openlink = null;
        if (redisUtil.hasKey(key)){
            Openlink = (String)redisUtil.getObejct(key);
        }else {
            WxOpenLink wxOpenLink =  wxOpenLinkService.getOne(new LambdaQueryWrapper<WxOpenLink>()
                    .eq(WxOpenLink::getKeyStatus  , 0)
                    .orderByAsc(WxOpenLink::getUsdDate)
                    .last("limit 1"));
            if (wxOpenLink == null){
                return null ;
            }else {
                Openlink = wxOpenLink.getOpenLink();
                redisUtil.setForObjectTimeCustom(key, Openlink, 1, TimeUnit.DAYS);
                wxOpenLinkService.update(new LambdaUpdateWrapper<WxOpenLink>()
                        .eq(WxOpenLink::getId,wxOpenLink.getId())
                        .set(WxOpenLink::getUsdDate , new Date())
                        .set(WxOpenLink::getKeyStatus , 1));
            }
        }
        return Openlink;
    }

    @Override
    public String getOpenlink(String ip ,Map<String, String> map) {
        log.info(ip);
        String key = RedisConstants.WxProgram_OpenLink+ip ;
        String Openlink = null;
        if (redisUtil.hasKey(key)){
            Openlink = (String)redisUtil.getObejct(key);
        }else {
            WxProgramConfig wxProgramConfig =  getWxProgramConfig();
            Openlink = sendOpenlink(wxProgramConfig , map);
            redisUtil.setForObjectTimeCustom(key, Openlink, 1, TimeUnit.DAYS);
        }
        return Openlink;
    }

    @Override
    public void addOpenlink(Integer num) {
        if (num == 0){
            Integer count = wxOpenLinkService.count(new LambdaQueryWrapper<WxOpenLink>()
                    .eq(WxOpenLink::getKeyStatus , 0));
            if (count<=300000){
                num = 300000 -count ;
            }

        }
        WxProgramConfig wxProgramConfig =  getWxProgramConfig();
        List<WxOpenLink> wxOpenLinks = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            String openlink = sendOpenlink(wxProgramConfig ,null);
            wxOpenLinks.add(WxOpenLink.builder()
                            .usdDate(new Date())
                            .wxProgramConfigId(wxProgramConfig.getId())
                            .openLink(openlink)
                            .keyStatus(0)
                    .build());
        }
        wxOpenLinkService.saveBatch(wxOpenLinks);
    }


}
